Feat/at reference#3560
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Propagates Written by Cursor Bugbot for commit d5ba7c4. This will update automatically on new commits. Configure here. |
apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx
Show resolved
Hide resolved
apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx
Show resolved
Hide resolved
Greptile SummaryThis PR adds @mention-based resource referencing to the home chat interface, allowing users to type Key changes:
Notable concerns:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
actor User
participant UI as UserInput
participant MM as ResourceMentionMenu
participant CM as useContextManagement
participant HC as useChat (sendMessage)
participant API as /api/mothership/chat
User->>UI: Types @resource or clicks + Resources
UI->>MM: Show mention menu (portal to body)
User->>MM: Selects a resource
MM->>UI: onSelect(resource, fromMentionMenu)
UI->>UI: mapResourceToContext(resource)
UI->>CM: addContext(context)
CM-->>UI: selectedContexts updated
UI->>UI: Render ContextPills + highlight overlay
User->>UI: Submits message
UI->>HC: onSubmit(text, fileAttachments, contexts)
HC->>HC: Build userMessage with contexts
HC->>HC: setMessages([...prev, userMessage])
HC->>API: POST { message, contexts, fileAttachments, ... }
API->>API: Validate with Zod schema
API->>API: Store contexts in DB (copilotChats)
API-->>HC: SSE stream response
HC-->>UI: isSending = false, messages updated
UI->>UI: Render UserMessageContent with mention highlights
|
| import { cn } from '@/lib/core/utils/cn' | ||
| import type { ChatMessageContext } from '../types' | ||
| import { useWorkflowRegistry } from '@/stores/workflows/registry/store' |
There was a problem hiding this comment.
Unused cn import
cn is imported on line 3 but is never referenced anywhere in this file. This will likely trigger a lint warning. It should be removed.
| import { cn } from '@/lib/core/utils/cn' | |
| import type { ChatMessageContext } from '../types' | |
| import { useWorkflowRegistry } from '@/stores/workflows/registry/store' | |
| import type { ChatMessageContext } from '../types' | |
| import { useWorkflowRegistry } from '@/stores/workflows/registry/store' |
| style={{ | ||
| position: 'fixed', | ||
| top: `${caretViewport.top}px`, | ||
| left: `${caretViewport.left}px`, | ||
| width: '1px', | ||
| height: '1px', |
There was a problem hiding this comment.
table and file resource IDs are dropped silently
For the table and file resource types, the resource's id is not included in the returned context object. The API schema also has no tableId/fileId field, so the backend receives only a label string for these resources — it cannot resolve or retrieve the actual content of the referenced table or file. If these resource types are intended to be actionable in context (not just decorative labels), either a new ID field needs to be added to the schema or these types should be excluded from the @mention resource list.
case 'table':
return { kind: 'docs', label: resource.title }
// resource.id is silently dropped — backend has no way to look up this table
case 'file':
return { kind: 'docs', label: resource.title }
// same issue for file| .filter((item) => item.name.toLowerCase().includes(searchQuery)) | ||
| .map((item) => ({ type, item })) | ||
| ) | ||
| } | ||
| // When no query, show all items flat | ||
| return availableResources.flatMap(({ type, items }) => | ||
| items.map((item) => ({ type, item })) | ||
| ) | ||
| }, [availableResources, query]) | ||
|
|
There was a problem hiding this comment.
Deep cross-feature import coupling
user-input.tsx in the home feature directly imports implementation hooks and utilities from the deeply nested copilot panel feature path:
@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks
@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/utils
This creates a tight coupling between two unrelated features. If the copilot panel's internal structure changes, the home feature breaks. Consider extracting the shared hooks (useCaretViewport, useContextManagement, useMentionMenu, useMentionTokens) and utilities into a shared location (e.g., @/hooks/ or @/lib/), following the established path alias patterns in the project.
Rule Used: Use established path alias patterns instead of dee... (source)
Learnt From
simstudioai/sim#233
apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/context-pills.tsx
Show resolved
Hide resolved
|
|
||
| document.addEventListener('keydown', handleKeyDown) | ||
| return () => document.removeEventListener('keydown', handleKeyDown) | ||
| }, [flatItems, activeIndex, handleSelect, onClose]) |
There was a problem hiding this comment.
Enter key blocked when mention menu has no results
Medium Severity
The ResourceMentionMenu registers a global document keydown listener that intercepts Enter/Tab and calls e.preventDefault(). Simultaneously, the textarea's handleKeyDown also intercepts Enter and prevents default when showMentionMenu is true. When the mention menu is visible but shows "No results", pressing Enter does nothing — the message cannot be submitted because both handlers block it. The user must press Escape first.
Additional Locations (1)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
There are 4 total unresolved issues (including 1 from previous review).
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| const tokenEnd = tokenStart + token.length | ||
| ranges.push({ start: tokenStart, end: tokenEnd, token, context: ctx }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Mention regex fails for tokens at text boundaries
Medium Severity
The computeMentionRanges regex pattern (^|\s)(@label)(\s|$) requires the mention token to be followed by whitespace or end-of-string. This means a mention at the end of the message text (which is common — users type @WorkflowName and hit send) will only match if there's a trailing space. Since the message is trimmed before sending (text.trim() in handleSubmit), trailing spaces are removed, so mentions at the very end of the user's message won't be highlighted in the rendered chat history.
| const tokenStart = match.index + leadingSpace.length | ||
| const tokenEnd = tokenStart + token.length | ||
| ranges.push({ start: tokenStart, end: tokenEnd, token, context: ctx }) | ||
| } |
There was a problem hiding this comment.
Adjacent mentions missed due to regex consuming shared whitespace
Medium Severity
In computeMentionRanges, the regex pattern (^|\s)(@label)(\s|$) with the g flag consumes the trailing whitespace as part of the match. When two mentions are separated by a single space (e.g., @Workflow1 @Workflow2), the space is consumed by the first match's (\s|$) group, so the second mention's required (^|\s) prefix can't match — the second mention is silently skipped and won't be highlighted in the rendered message.
| const tokenEnd = tokenStart + token.length | ||
| ranges.push({ start: tokenStart, end: tokenEnd, token, context: ctx }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Adjacent mention tokens miss highlighting due to whitespace consumption
Low Severity
In computeMentionRanges, the regex (^|\s)(@label)(\s|$) with the g flag consumes trailing whitespace as part of the match. When the same label appears twice separated by a single space, the first match consumes the space, causing the regex's lastIndex to skip past the second occurrence's required leading whitespace — the second mention won't be highlighted. Using a lookahead (?=\s|$) instead of (\s|$) would avoid consuming the boundary character.


Summary
Added @ing resources to reference them and insert it into context
Fixes #(issue)
Type of Change
Testing
Validated context is passed. Resource menu also updated and block colors persisted.
Checklist
Screenshots/Videos